//! 对象数据操作模块
//! 实现IObjectData接口，提供对象级别的数据操作

use async_trait::async_trait;
use futures_util::TryStreamExt;
use mongodb::bson::{Bson, Document};
use regex::Regex;
use serde_json::Value;

use crate::{
    models::{OperateResult, TokenModel},
};
use crate::storage::storage_provider::IStorage;

/// 对象键解析结构
#[derive(Debug)]
struct ObjectKey {
    root_key: Option<String>,
    select_path: Option<String>,
    has_error: bool,
    error: Option<String>,
}

impl ObjectKey {
    /// 解析对象键
    fn parse(&mut self, key: &str) -> &Self {
        // 实现对象键解析逻辑
        // 这里需要解析类似 "rootKey.selectPath" 的格式
        let parts: Vec<&str> = key.split('.').collect();
        
        if parts.is_empty() {
            self.has_error = true;
            self.error = Some("对象键不能为空".to_string());
            return self;
        }

        // 验证根键格式
        let root_re = Regex::new(r"^[_a-z0-9A-Z-.]{4,50}$").unwrap();
        if !root_re.is_match(parts[0]) {
            self.has_error = true;
            self.error = Some("对象名称必须是长度为4~50个字符的英文字母或('-','_')!".to_string());
            return self;
        }

        self.root_key = Some(parts[0].to_string());
        
        if parts.len() > 1 {
            self.select_path = Some(parts[1..].join("."));
        }

        self
    }

    /// 是否有根键
    fn has_root_key(&self) -> bool {
        self.root_key.is_some()
    }

    /// 是否有选择路径
    fn has_select_path(&self) -> bool {
        self.select_path.is_some()
    }

    /// 是否有错误
    fn has_error(&self) -> bool {
        self.has_error
    }

    /// 获取错误信息
    fn error(&self) -> Option<&str> {
        self.error.as_deref()
    }

    /// 创建根文档
    fn create_root(&self, data: Value) -> Document {
        let mut doc = Document::new();
        if let Some(path) = &self.select_path {
            doc.insert(path, mongodb::bson::to_bson(&data).unwrap_or(Bson::Null));
        }
        doc
    }
}

impl Default for ObjectKey {
    fn default() -> Self {
        Self {
            root_key: None,
            select_path: None,
            has_error: false,
            error: None,
        }
    }
}

/// 对象数据操作接口
/// 对应C#版本ObjectData部分
#[async_trait]
pub trait IObjectData: Send + Sync {
    /// 列出对象
    async fn list_objects(&self, token: &TokenModel, object_key: &str) -> OperateResult;

    /// 获取对象
    async fn get_object(&self, token: &TokenModel, object_key: &str) -> OperateResult;

    /// 设置对象
    async fn set_object(&self, token: &TokenModel, object_key: &str, object_value: Value) -> OperateResult;

    /// 删除对象
    async fn delete_object(&self, token: &TokenModel, object_key: &str) -> OperateResult;
}

/// 对象数据实现
pub struct ObjectData<S: IStorage + Send + Sync + 'static + ?Sized> {
    storage: std::sync::Arc<S>,
}

impl<S: IStorage + Send + Sync + 'static + ?Sized> ObjectData<S> {
    /// 创建新的对象数据实例
    pub fn new(storage: std::sync::Arc<S>) -> Self {
        Self { storage }
    }

    /// 常量定义
    pub const OBJECT_COLL_NAME: &'static str = "_system-objects";

    /// 尝试获取对象集合
    async fn try_get_object_collection(&self, token: &TokenModel, object_key: &str) -> Result<(Box<dyn crate::storage::storage_provider::ICollection<Document>>, ObjectKey), String> {
        let mut key = ObjectKey::default();
        key.parse(object_key);

        if key.has_error() {
            return Err(key.error().unwrap_or("未知错误").to_string());
        }

        let collection = self.storage.get_document_collection(&token.db_name(), Self::OBJECT_COLL_NAME);
        Ok((collection, key))
    }
}

#[async_trait]
impl<S: IStorage + Send + Sync + 'static + ?Sized> IObjectData for ObjectData<S> {
    async fn list_objects(&self, token: &TokenModel, object_key: &str) -> OperateResult {
        match self.try_get_object_collection(token, object_key).await {
            Ok((collection, key)) => {
                if key.has_root_key() {
                    // 列出特定根键下的对象
                    let root_key = key.root_key.as_ref().unwrap();
                    let match_doc = Document::from_iter([("id".to_string(), Bson::String(root_key.clone()))]);
                    let project_doc = Document::from_iter([("id".to_string(), Bson::Int32(1)), ("name".to_string(), Bson::Int32(1))]);
                    let pipeline = vec![
                        Document::from_iter([("$match".to_string(), Bson::Document(match_doc))]),
                        Document::from_iter([("$project".to_string(), Bson::Document(project_doc))]),
                    ];

                    match collection.aggregate(pipeline).await {
                        Ok(results) => {
                            OperateResult::success(serde_json::to_value(results).unwrap_or(Value::Null))
                        }
                        Err(e) => OperateResult::fail(&format!("列出对象失败: {}", e)),
                    }
                } else {
                    // 列出所有对象
                    match collection.find(Document::new()).await {
                        Ok(results) => {
                            OperateResult::success(serde_json::to_value(results).unwrap_or(Value::Null))
                        }
                        Err(e) => OperateResult::fail(&format!("列出对象失败: {}", e)),
                    }
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn get_object(&self, token: &TokenModel, object_key: &str) -> OperateResult {
        match self.try_get_object_collection(token, object_key).await {
            Ok((collection, key)) => {
                if let Some(ref root_key) = key.root_key {
                    let filter = Document::from_iter([("id".to_string(), Bson::String(root_key.clone()))]);
                    match collection.find_one(filter).await {
                        Ok(Some(doc)) => OperateResult::success(serde_json::to_value(doc).unwrap_or(Value::Null)),
                        Ok(None) => OperateResult::fail(&format!("对象键[{}]不存在!", object_key)),
                        Err(e) => OperateResult::fail(&format!("获取对象失败: {}", e)),
                    }
                } else {
                    OperateResult::fail(&format!("对象键[{}]不正确!", object_key))
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn set_object(&self, token: &TokenModel, object_key: &str, object_value: Value) -> OperateResult {
        match self.try_get_object_collection(token, object_key).await {
            Ok((collection, key)) => {
                if let Some(ref root_key) = key.root_key {
                    let filter = Document::from_iter([("id".to_string(), Bson::String(root_key.clone()))]);
                    let root_doc = key.create_root(object_value.clone());
                    let update = Document::from_iter([("$set".to_string(), Bson::Document(root_doc))]);

                    // 直接尝试更新对象
                    match collection.update_one(filter, update).await {
                        Ok(_) => OperateResult::success(Value::Null),
                        Err(e) => OperateResult::fail(&format!("设置对象失败: {}", e)),
                    }
                } else {
                    OperateResult::fail(&format!("对象键[{}]不正确!", object_key))
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn delete_object(&self, token: &TokenModel, object_key: &str) -> OperateResult {
        match self.try_get_object_collection(token, object_key).await {
            Ok((collection, key)) => {
                if let Some(ref root_key) = key.root_key {
                    if !key.has_select_path() {
                        // 删除整个文档
                        let filter = Document::from_iter([("id".to_string(), Bson::String(root_key.clone()))]);
                        match collection.delete_one(filter).await {
                            Ok(_) => OperateResult::success(Value::Null), // 简化返回，因为ICollection::delete_one不返回删除计数
                            Err(e) => OperateResult::fail(&format!("删除对象失败: {}", e)),
                        }
                    } else {
                        // 删除特定路径
                        let filter = Document::from_iter([("id".to_string(), Bson::String(root_key.clone()))]);
                        let unset_doc = Document::from_iter([(key.select_path.unwrap().to_string(), Bson::String("".to_string()))]);
                        let update = Document::from_iter([("$unset".to_string(), Bson::Document(unset_doc))]);

                        match collection.update_one(filter, update).await {
                            Ok(_) => OperateResult::success(Value::Null), // 简化返回，因为ICollection::update_one不返回修改计数
                            Err(e) => OperateResult::fail(&format!("删除对象路径失败: {}", e)),
                        }
                    }
                } else {
                    OperateResult::fail(&format!("对象键[{}]不正确!", object_key))
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }
}